package com.abapi.pay.service;

import com.abapi.pay.AbapiPayProperties;
import com.abapi.pay.SpringContext;
import com.abapi.pay.core.annotation.AbapiPayCallback;
import com.abapi.pay.core.annotation.AbapiPayHandler;
import com.abapi.pay.core.biz.Encode;
import com.abapi.pay.core.constans.MessageType;
import com.abapi.pay.core.dto.MessageDTO;
import com.abapi.pay.core.dto.RegisterDTO;
import com.alibaba.fastjson.JSON;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import org.springframework.context.ApplicationContext;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Stream;

/**
 * @Author ldx
 * @Date 2019/11/1 13:26
 * @Description
 * @Version 1.0.0
 */
public class RegisterService {

    final AbapiPayProperties abapiPayProperties;

    public RegisterService(AbapiPayProperties abapiPayProperties){
        this.abapiPayProperties = abapiPayProperties;
    }

    public void register(ChannelHandlerContext ctx){
        ApplicationContext context = SpringContext.getApplicationContext();
        String[] endpointBeanNames = context.getBeanNamesForAnnotation(AbapiPayHandler.class);

        Map<String,String> registMap = new HashMap<>();

        Stream.of(endpointBeanNames).forEach(beanName->{
            Class handlerCls = context.getType(beanName);
            Method[] methods = handlerCls.getDeclaredMethods();

            for(Method method : methods){
                AbapiPayCallback annotation = method.getAnnotation(AbapiPayCallback.class);
                if(annotation == null) {continue;}
                registMap.put(annotation.backName()+"_"+annotation.payType().toString(),handlerCls.getName());
            }
        });

        RegisterDTO dto = new RegisterDTO();
        dto.setProjectName(abapiPayProperties.getProjectName());
        dto.setClassName(JSON.toJSONString(registMap));

        MessageDTO resultDTO = new MessageDTO();
        resultDTO.setType(MessageType.REGISTER);
        resultDTO.setBody(dto);

        ByteBuf buf = ctx.channel().alloc().buffer();
        buf.writeBytes(Encode.encode(resultDTO));
        ctx.channel().writeAndFlush(buf);

    }

}
